﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Drawing.Imaging;
using System.Runtime.InteropServices;

namespace Test
{
    public partial class TestMarshalForm : Form
    {
        public TestMarshalForm()
        {
            InitializeComponent();
        }

        private static int MarshalGet(IntPtr ptr, int index)
        {
            return Marshal.ReadInt32(ptr, index * 4);
        }

        private void btnTestMarshal_Click(object sender, EventArgs e)
        {

            // create a big array.
            int numElements = 10 * 1024 * 1024;
            int[] array = new int[numElements];
            int n = array.Length;

            // assign.
            DateTime t1 = DateTime.Now;
            int sum1 = 0;
            for (int i = 0; i < n; i++)
            {
                array[i] = i;
                int v = array[i];
                sum1 += v;
            }
            TimeSpan dt1 = DateTime.Now - t1;

            // marshal assign.
            GCHandle handle = GCHandle.Alloc(array, GCHandleType.Pinned);
            IntPtr ptr = handle.AddrOfPinnedObject();
            DateTime t2 = DateTime.Now;
            int sum2 = 0;
            for (int i = 0; i < n; i++)
            {
                int v = MarshalGet(ptr, i);
                Marshal.WriteInt32(ptr, i * 4, v);
                sum2 += v;
            }
            TimeSpan dt2 = DateTime.Now - t2;
            handle.Free();

            lblResult.Text = string.Format(
                "Array access: {0:0} ms [{2}]\r\n" +
                "Marshal access: {1:0} ms [{3}]",
                dt1.TotalMilliseconds,
                dt2.TotalMilliseconds,
                sum1,
                sum2);
        }
    }
}
